package zisu.netty.practice.RPC.client.proxy;

import io.protostuff.Rpc;
import zisu.netty.practice.RPC.client.RpcClientHandler;
import zisu.netty.practice.RPC.client.RpcConnectManager;
import zisu.netty.practice.RPC.client.RpcFuture;
import zisu.netty.practice.RPC.client.codec.RpcRequest;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * @Desc: ""
 * @Author: caixiang
 * @DATE: 2021/1/23 15:34
 */
public class RpcProxyImpl<T> implements InvocationHandler,RpcAsyncProxy {

    private Class<T> clazz;

    private long timeout;

    public RpcProxyImpl(Class<T> clazz,long timeout){
        this.clazz = clazz;
        this.timeout = timeout;
    }

    /**
     * 代理接口调用方式（同步方式），
     * */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //1.设置请求对象
        RpcRequest request = new RpcRequest();
        request.setRequestId(UUID.randomUUID().toString());
        request.setClassName(method.getDeclaringClass().getName());
        request.setMethodName(method.getName());
        request.setParameterTypes(method.getParameterTypes());
        request.setParameters(args);

        //2.选择一个合适的任务处理器
        //会给我们返回一个可用的handler
        RpcClientHandler handler = RpcConnectManager.getInstance().chooseHandler();

        //3.发送真正的客户端请求  返回结果。
        //发送request 是异步的（丢到线程池）
        RpcFuture future = handler.sendRequest(request);
        return future.get(timeout, TimeUnit.SECONDS);
        //return future.get();
    }

    /**
     * 异步方式，把RpcFuture 给抛出去，抛给业务方 让他们自己去做一个实际的等待。
     * */
    @Override
    public RpcFuture call(String funcName, Object... args) {
        RpcRequest request = new RpcRequest();
        request.setRequestId(UUID.randomUUID().toString());
        request.setClassName(this.clazz.getName());
        request.setMethodName(funcName);

        request.setParameters(args);
        //TODO 对应的参数类型 应该通过 类类型 + 方法名称 通过发射得到parameterType
        Class<?>[] parameterTypes = new Class[args.length];
        for(int i=0;i<args.length;i++){
            parameterTypes[i] = getClassType(args[i]);
        }
        request.setParameterTypes(parameterTypes);

        //2.选择一个合适的任务处理器
        //会给我们返回一个可用的handler
        RpcClientHandler handler = RpcConnectManager.getInstance().chooseHandler();

        //3.发送真正的客户端请求  返回结果。
        //发送request 是异步的（丢到线程池）
        RpcFuture future = handler.sendRequest(request);

        return future;
    }

    private Class<?> getClassType(Object obj) {
        Class<?> classType = obj.getClass();
        String typeName = classType.getName();
        if (typeName.equals("java.lang.Integer")) {
            return Integer.TYPE;
        } else if (typeName.equals("java.lang.Long")) {
            return Long.TYPE;
        } else if (typeName.equals("java.lang.Float")) {
            return Float.TYPE;
        } else if (typeName.equals("java.lang.Double")) {
            return Double.TYPE;
        } else if (typeName.equals("java.lang.Character")) {
            return Character.TYPE;
        } else if (typeName.equals("java.lang.Boolean")) {
            return Boolean.TYPE;
        } else if (typeName.equals("java.lang.Short")) {
            return Short.TYPE;
        } else if (typeName.equals("java.lang.Byte")) {
            return Byte.TYPE;
        }
        return classType;
    }
}
